home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 6
/
Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso
/
039a
/
d3d.zip
/
CABLE.C
< prev
next >
Wrap
Text File
|
1991-08-30
|
7KB
|
257 lines
/* CABLE: This program reads a file that represents a space curve, and
writes a file that represents a cable. The circular cable section
will be a regular polygon with n vertices; it approximates a circle
with radius R. Both n and R are read from the keyboard. The program
is to be linked together with the module TRAFO, in which the functions
'initrotate ' and 'rotate' are defined.
*/
#include <stdio.h>
#include <math.h>
#include <alloc.h>
#include <process.h>
void initrotate( double a1, double a2, double a3,
double v1, double v2, double v3, double alpha);
void rotate(double x, double y, double z,
double *px1, double *py1, double *pz1);
int zero(double x);
double *getdouble(int n);
double *enlarge(double *px, int N);
void ermes(char *s);
main()
{
char infil[30], outfil[30];
int i, n, j, m, jn, jn0, k, tablesize;
double R, *x, *y, *z, xC0, yC0, zC0, xC1, yC1, zC1, xC2, yC2, zC2,
*xC, *yC, *zC, a, b, c, d, rx, ry, rz, pi, theta, Len, *getdouble(),
*enlarge(), xA, xB, yA, yB, zA, zB, dx, dy, dz, d0, c1, c2, c0,
xM, yM, zM, e1, e2, e0, denom, lambda, mu, xP, yP, zP, xAP, yAP, zAP,
xBP, yBP, zBP, v1, v2, v3, cosphi, phi;
FILE *fpin, *fpout;
printf("Input file: ");
scanf("%s", infil);
if((fpin = fopen(infil, "r")) == NULL)
ermes("File not available");
if
(fscanf(fpin, "%*d %lf %lf %lf", &xC0, &yC0, &zC0) != 3 ||
fscanf(fpin, "%*d %lf %lf %lf", &xC1, &yC1, &zC1) != 3 ||
fscanf(fpin, "%*d %lf %lf %lf", &xC2, &yC2, &zC2) != 3)
ermes("Input file incorrect");
printf("Output file: "); scanf("%s", outfil);
if((fpout = fopen(outfil, "w")) == NULL)
ermes("Problem with output file");
printf("How many points on each circle? "); scanf("%d", &n);
printf("Radius: "); scanf("%lf", &R);
a=xC2 - xC0;
b=yC2 - yC0;
c=zC2 - zC0;
d = a*xC1 + b*yC1 + c*zC1;
/* First circle has center (xC1, yC1, zC1), radius R, and lies
in the plane ax + by + cz = d */
x = getdouble(n);
y = getdouble(n);
z = getdouble(n);
if(zero(a) && zero(b)) {
rx = 0;
ry = c;
rz = -b;
}
else {
rx = b;
ry = -a;
rz = 0;
}
Len = sqrt(rx*rx + ry*ry + rz*rz);
rx /= Len;
ry /= Len;
rz /= Len;
/* (rx, ry, rz) is a unit vector perpendicular to (a, b, c) */
x[0] = xC1 + rx*R;
y[0] = yC1 + ry*R;
z[0] = zC1 + rz*R;
pi = 4.0 * atan(1.0);
theta = 2.0*pi/n;
/* Computation of n points on the first circle */
initrotate(xC1, yC1, zC1, a, b, c, theta);
for(i=1; i<n; i++)
rotate(x[i-1], y[i-1], z[i-1], x+i, y+i, z+i); /* x+i == &x[i] */
/* Count the number of circles (number of points -1 from input file) */
m = 2;
while(fscanf(fpin, "%*d %lf %lf %lf", &xC0, &yC0, &zC0) == 3)
m++;
tablesize = m*n;
x = enlarge(x, tablesize);
y = enlarge(y, tablesize);
z = enlarge(z, tablesize);
rewind(fpin);
fscanf(fpin, "%*d %lf %lf %lf", &xC0, &yC0, &zC0); /* Skip 1 */
xC = getdouble(m); /* get pointers to memory tracts */
yC = getdouble(m);
zC = getdouble(m);
for(j=0; j<m; j++)
fscanf(fpin, "%*d %lf %lf %lf", xC+j, yC+j, zC+j);
fclose(fpin);
/* (xC[0], yC[0], zC[0]) is now the center of the given circle,
lying in plane ax + by + cz = d, and with radius R. The n
relevant points on this circle have already been computed;
their coordinates are
x[0], y[0], z[0], ..., x[n-1],y[n-1],z[n-1].
The other m-1 circles will be derived from this first one by means
of rotations.
*/
for(j=1; j<m; j++) {
jn = j*n;
jn0 = jn - n;
xA = xC[j-1];
yA = yC[j-1];
zA = zC[j-1];
xB = xC[j];
yB = yC[j];
zB = zC[j];
dx = xB - xA;
dy = yB - yA;
dz = zB - zA;
c1 = a*a + b*b + c*c;
c2 = a*dx + b*dy + c*dz;
c0 = d - a*xA - b*yA - c*zA;
xM = 0.5*(xA + xB);
yM = 0.5*(yA + yB);
zM = 0.5*(zA + zB);
d0 = dx*xM + dy*yM + dz*zM;
e1 = dx*a + dy*b + dz*c;
e2 = dx*dx + dy*dy + dz*dz;
e0 = d0 - dx*xA - dy*yA - dz*zA;
denom = c1*e2 - c2*e1;
if(fabs(denom) < 1.e-12) {
/* Direction does not change.
Instead of using a point P indefinately far away,
we perform a simple translation: */
for(i=0; i<n; i++) {
x[jn+i] = x[jn0+i] +dx;
y[jn+i] = y[jn0+i] +dy;
z[jn+i] = z[jn0+i] +dz;
}
}
else {
/* Direction changes.
The polygon will be rotated through the angle phi
about the vector v passing through the point P. */
lambda = (c0*e2 - c2*e0)/denom;
mu = (c1*e0 - c0*e1)/denom;
xP = xA + lambda*a + mu*dx;
yP = yA + lambda*b + mu*dy;
zP = zA + lambda*c + mu*dz;
/* Point P(of intersection of three planes) is center of rotation */
xAP = xA - xP;
yAP = yA - yP;
zAP = zA - zP;
xBP = xB - xP;
yBP = yB - yP;
zBP = zB - zP;
v1 = yAP*zBP - yBP*zAP;
v2 = zAP*xBP - zBP*xAP;
v3 = xAP*yBP - xBP*yAP;
/* (v1, v2, v3) is the direction of the axis of rotation */
cosphi = (xAP*xBP + yAP*yBP + zAP*zBP)/
sqrt((xAP*xAP + yAP*yAP + zAP*zAP)*
(xBP*xBP + yBP*yBP + zBP*zBP));
phi = (cosphi == 0 ? 0.5*pi :
atan(sqrt(1.0 - cosphi*cosphi)/cosphi));
/* phi is the angle of rotation */
initrotate(xP, yP, zP, v1, v2, v3, phi);
for(i=0; i<n; i++)
rotate(x[jn0+i], y[jn0+i], z[jn0+i], x+jn+i, y+jn+i, z+jn+i);
initrotate(0.0, 0.0, 0.0, v1, v2, v3, phi);
rotate(a, b, c, &a, &b, &c);
}
d = a*xC[j] + b*yC[j] + c*zC[j];
}
for(k=0; k<m*n; k++)
fprintf(fpout, "%d %f %f %f\n", k+1, x[k], y[k], z[k]);
fprintf(fpout, "Faces:\n");
for(k=n-1; k>=0; k--)
fprintf(fpout, " %d", k+1);
fprintf(fpout, ".\n");
for(k=(m-1)*n; k<m*n; k++)
fprintf(fpout, " %d", k+1);
fprintf(fpout, ".\n");
for(j=1; j<m; j++) {
jn = j*n + 1;
jn0 = jn - n;
for(i=0; i<n-1; i++) {
fprintf(fpout, " %d %d %d.\n", jn+i+1, -(jn0+i), jn0+i+1);
fprintf(fpout, " %d %d %d.\n", jn0+i, -(jn+i+1), jn+i);
}
fprintf(fpout, " %d %d %d.\n", jn, -(jn0+n-1), jn0);
fprintf(fpout, " %d %d %d.\n", jn0+n-1, -jn, jn+n-1);
}
fclose(fpout);
}
int zero(double x)
{
return fabs(x) < 1.e-5;
}
double *getdouble(int n)
{
double *p;
if((p = (double *)malloc(n*sizeof(double))) == NULL)
ermes("Not enough memory");
return p;
}
double *enlarge(double *px, int N)
{
if((px = (double *)realloc(px, N*sizeof(double))) == NULL)
ermes("Not enough memory");
return px;
}
void ermes(char *s)
{
printf(s);
exit(1);
}